import type { SerialPort } from '../models/up_serial_port.ts';
import type { BaseResponse } from '../models/up_response.ts';
import type {
  EEPromParam,
  RAMParam,
  EEPromParamRequest,
  RAMParamRequest,
} from '../models/up_request.ts';
import { SerialPortFactory } from '../models/factories/SerialPortFactory';
import apiClient from '../utils/axiosInterceptors';

type ParamType = EEPromParam | RAMParam;
type RequestType = EEPromParamRequest | RAMParamRequest;

export class ReadService {
  /** 通用读取参数方法 */
  private static async readParam<T extends ParamType>(
    url: string,
    request: RequestType
  ): Promise<number[]> {
    return apiClient
      .post<BaseResponse<number[]>>(url, request)
      .then((response) => {
        if (response.data.status && response.data.data) {
          return response.data.data;
        } else {
          throw SerialPortFactory.createSerialError(
            response.data.message || 'Unknown error'
          );
        }
      });
  }

  static async readEEProm(
    serial_id: string,
    protocol_id: number,
    param: EEPromParam
  ): Promise<number[]> {
    return this.readParam('/read/eeprom_param', {
      serial_id,
      protocol_id,
      param,
    });
  }

  static async readRAM(
    serial_id: string,
    protocol_id: number,
    param: RAMParam
  ): Promise<number[]> {
    return this.readParam('/read/ram_param', { serial_id, protocol_id, param });
  }

  /** 校验返回值长度 */
  private static assertLength<T>(
    data: number[],
    expected: number,
    errMsg: string
  ): T {
    if (data.length === expected) {
      return data as unknown as T;
    }
    throw new Error(`${errMsg}，实际返回: ${data}`);
  }

  static async readSingleEEProm(
    serial_id: string,
    protocol_id: number,
    param: EEPromParam
  ): Promise<number> {
    const data = await this.readEEProm(serial_id, protocol_id, param);
    return this.assertLength<number>(data, 1, '期望返回单个值');
  }

  static async readRangeEEProm(
    serial_id: string,
    protocol_id: number,
    param: EEPromParam
  ): Promise<[number, number]> {
    const data = await this.readEEProm(serial_id, protocol_id, param);
    return this.assertLength<[number, number]>(data, 2, '期望返回两个值');
  }

  static async read4ByteEEProm(
    serial_id: string,
    protocol_id: number,
    param: EEPromParam
  ): Promise<[number, number, number, number]> {
    const data = await this.readEEProm(serial_id, protocol_id, param);
    return this.assertLength<[number, number, number, number]>(
      data,
      4,
      '期望返回四个值'
    );
  }

  static async readSingleRAM(
    serial_id: string,
    protocol_id: number,
    param: RAMParam
  ): Promise<number> {
    const data = await this.readRAM(serial_id, protocol_id, param);
    return this.assertLength<number>(data, 1, '期望返回单个值');
  }

  static async readRangeRAM(
    serial_id: string,
    protocol_id: number,
    param: RAMParam
  ): Promise<[number, number]> {
    const data = await this.readRAM(serial_id, protocol_id, param);
    return this.assertLength<[number, number]>(data, 2, '期望返回两个值');
  }

  static async read4ByteRAM(
    serial_id: string,
    protocol_id: number,
    param: RAMParam
  ): Promise<[number, number, number, number]> {
    const data = await this.readRAM(serial_id, protocol_id, param);
    return this.assertLength<[number, number, number, number]>(
      data,
      4,
      '期望返回四个值'
    );
  }
}
